package cn.stylefeng.roses.kernel.oauth2.modular.service.impl;

import cn.stylefeng.roses.kernel.auth.api.AuthServiceApi;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse;
import cn.stylefeng.roses.kernel.oauth2.api.constants.Oauth2Constants;
import cn.stylefeng.roses.kernel.oauth2.api.exception.Oauth2Exception;
import cn.stylefeng.roses.kernel.oauth2.api.exception.enums.Oauth2ExceptionEnum;
import cn.stylefeng.roses.kernel.oauth2.modular.entity.OauthUserInfo;
import cn.stylefeng.roses.kernel.oauth2.modular.factory.OAuthUserInfoFactory;
import cn.stylefeng.roses.kernel.oauth2.modular.factory.OauthSysUserCreateFactory;
import cn.stylefeng.roses.kernel.oauth2.modular.service.LoginService;
import cn.stylefeng.roses.kernel.oauth2.modular.service.Oauth2UserInfoService;
import cn.stylefeng.roses.kernel.sys.api.pojo.user.SimpleUserDTO;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUser;
import cn.stylefeng.roses.kernel.sys.modular.user.pojo.request.SysUserOrgRequest;
import cn.stylefeng.roses.kernel.sys.modular.user.service.SysUserOrgService;
import cn.stylefeng.roses.kernel.sys.modular.user.service.SysUserRoleService;
import cn.stylefeng.roses.kernel.sys.modular.user.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 默认第三方登录逻辑
 *
 * @author fengshuonan
 * @date 2022/7/1 17:45
 */
@Service
public class DefaultLoginService implements LoginService {

    @Resource
    private Oauth2UserInfoService oauth2UserInfoApi;

    @Resource
    private AuthServiceApi authServiceApi;

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysUserOrgService sysUserOrgService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String oauthLogin(AuthUser oauthUser) {

        if (oauthUser == null) {
            throw new Oauth2Exception(Oauth2ExceptionEnum.OAUTH_RESPONSE_ERROR);
        }

        // 当前无登录用户，创建用户或根据已有绑定用户的账号登录
        String account = getOauthUserAccount(oauthUser);

        // 执行原有系统登录逻辑
        LoginResponse loginResponse = authServiceApi.loginWithUserName(account);

        // 返回token
        return loginResponse.getToken();
    }

    /**
     * 绑定当前用户的source和openId
     *
     * @author fengshuonan
     * @date 2022/7/1 17:46
     */
    private void bindOAuthUser(Long userId, AuthUser oauthUser) {

        // 先判断当前系统这个openId有没有人用
        LambdaQueryWrapper<OauthUserInfo> queryWrapper = new LambdaQueryWrapper<OauthUserInfo>()
                .eq(OauthUserInfo::getSource, oauthUser.getSource())
                .and(i -> i.eq(OauthUserInfo::getUuid, oauthUser.getUuid()))
                .and(i -> i.ne(OauthUserInfo::getUserId, userId));
        List<OauthUserInfo> oauthUserInfos = this.oauth2UserInfoApi.list(queryWrapper);

        // 已有人绑定，抛出异常
        if (oauthUserInfos != null && oauthUserInfos.size() > 0) {
            throw new Oauth2Exception(Oauth2ExceptionEnum.OPEN_ID_ALREADY_BIND);
        } else {
            // 新建一条绑定记录
            OauthUserInfo oAuthUserInfo = OAuthUserInfoFactory.createOAuthUserInfo(userId, oauthUser);
            this.oauth2UserInfoApi.save(oAuthUserInfo);
        }
    }

    /**
     * 通过第三方登录的信息创建本系统用户
     *
     * @author fengshuonan
     * @date 2019/6/9 19:07
     */
    private String getOauthUserAccount(AuthUser oauthUser) {

        // 先判断当前系统这个openId有没有人用
        LambdaQueryWrapper<OauthUserInfo> queryWrapper =
                new LambdaQueryWrapper<OauthUserInfo>()
                        .eq(OauthUserInfo::getSource, oauthUser.getSource())
                        .and(i -> i.eq(OauthUserInfo::getUuid, oauthUser.getUuid()));
        OauthUserInfo oauthUserInfos = this.oauth2UserInfoApi.getOne(queryWrapper);

        // 已有人绑定，直接返回这个人的账号，进行登录
        if (oauthUserInfos != null) {
            Long userId = oauthUserInfos.getUserId();
            SimpleUserDTO sysUserDTO = this.sysUserService.getUserInfoByUserId(userId);
            if (sysUserDTO != null) {
                return sysUserDTO.getAccount();
            } else {
                throw new Oauth2Exception(Oauth2ExceptionEnum.CANT_FIND_OAUTH2);
            }
        } else {

            // 没有人绑定的创建这个人的本系统用户
            SysUser sysUser = OauthSysUserCreateFactory.createOAuth2User(oauthUser);
            this.sysUserService.save(sysUser);

            // 创建OAuth2用户默认角色
            sysUserRoleService.bindUserDefaultRole(sysUser.getUserId());

            // 创建OAuth2用户默认部门信息
            SysUserOrgRequest sysUserOrgRequest = new SysUserOrgRequest();
            sysUserOrgRequest.setUserId(sysUser.getUserId());
            sysUserOrgRequest.setOrgId(Oauth2Constants.DEFAULT_OAUTH2_ORG_ID);
            sysUserOrgService.add(sysUserOrgRequest);

            // 新建一条oauth2绑定记录
            OauthUserInfo oAuthUserInfo = OAuthUserInfoFactory.createOAuthUserInfo(sysUser.getUserId(), oauthUser);
            this.oauth2UserInfoApi.save(oAuthUserInfo);

            return sysUser.getAccount();
        }
    }

}
